package com.liuqianfei.markme.rules.block;

import com.liuqianfei.markme.common.Utils;
import com.liuqianfei.markme.core.Token;
import com.liuqianfei.markme.rules.AbstractState;
import com.liuqianfei.markme.rules.IAction;
import com.liuqianfei.util.StringUtil;

import java.util.ArrayList;

/**
 * heading (#, ##, ...)
 * @author liuqianfei
 */
public class HeadingAction implements IAction
{
    @Override
    public boolean parse(AbstractState state, boolean silent, int startLine, int endLine)
    {
        char ch;
        Token token;
        int level, tmp, pos = state.getbMarks(startLine) + state.gettShift(startLine), max = state.geteMarks(startLine);

        ch  = state.getSrc().charAt(pos);

        if (ch != 0x23/* # */ || pos >= max)
            return false;

        // count heading level
        level = 1;
        ch = state.getSrc().charAt(++pos);
        while (ch == 0x23/* # */ && pos < max && level <= 6)
        {
            level++;
            ch = state.getSrc().charAt(++pos);
        }

        if (level > 6 || (pos < max && !Utils.isSpace(ch)))
            return false;

        if (silent)
            return true;

        // Let's cut tails like '    ###  ' from the end of string

        max = state.skipSpacesBack(max, pos);
        tmp = state.skipCharsBack(max, 0x23, pos); // #
        if (tmp > pos && Utils.isSpace(state.getSrc().charAt(tmp - 1)))
            max = tmp;

        state.setLine(startLine + 1);

        token        = state.push("heading_open", "h" + String.valueOf(level), 1);
        token.markup = StringUtil.slice("########", 0, level);
        token.map    = new int[]{startLine, state.getLine()};

        token          = state.push("inline", "", 0);
        token.content  = StringUtil.slice(state.getSrc(), pos, max).trim();
        token.map      = new int[]{startLine, state.getLine()};
        token.children = new ArrayList<>();

        token        = state.push("heading_close", "h" + String.valueOf(level), -1);
        token.markup = StringUtil.slice("########", 0, level);

        return true;
    }
}
